package com.boss.fileapp.util;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * 校验
 */
public class MACUtils {
    /**
     * DES 加密函数,keybyte是加密密钥，8个字节(64bit)；src是明文数据
     * ECB，无填充
     * @param keybyte
     * @param src
     * @return
     */
    public static byte[] enDES(byte[] keybyte,byte[] src){
        try {
            //生成密钥
            SecretKey deskey = new SecretKeySpec(keybyte, "DES");
            //加密
            Cipher c1 = Cipher.getInstance("DES/ECB/NoPadding");
            c1.init(Cipher.ENCRYPT_MODE, deskey);
            return c1.doFinal(src);//在单一方面的加密或解密
        } catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
    /**
     * DES 解密函数,keybyte是加密密钥，8个字节(64bit)；src是密文数据
     * ECB，无填充
     * @param keybyte
     * @param src
     * @return
     */
    public static byte[] deDES(byte[] keybyte,byte[] src){
        try {
            //生成密钥
            SecretKey deskey = new SecretKeySpec(keybyte, "DES");
            //解密
            Cipher c1 = Cipher.getInstance("DES/ECB/NoPadding");
            c1.init(Cipher.DECRYPT_MODE, deskey);
            return c1.doFinal(src);
        } catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
    /**
     * XOR 两个字节数组进行异或
     * @param edata
     * @param temp
     * @return
     */
    private static byte[] XOR(byte[] edata, byte[] temp) {
        byte [] result = new byte[8];
        for (int i = 0 , j = result.length ; i < j; i++) {
            result [i] = (byte) ((edata[i]&0xFF) ^ ( temp[i]&0xFF));
        }
        return result;
    }
    /**
     * 将十六进制字符串转换成字节流
     * @param b
     * @return 字节流
     */
    public static  byte[] hex2byte(byte[] b) {
        if ((b.length % 2) != 0)
            throw new IllegalArgumentException("长度不是偶数");
        byte[] b2 = new byte[b.length / 2];
        for (int n = 0; n < b.length; n += 2) {
            String item = new String(b, n, 2);
            b2[n / 2] = (byte) Integer.parseInt(item, 16);
        }
        return b2;
    }
    /**
     * 将字节流转换成十六进制字符串
     * @param b
     * @return 十六进制字符串
     */
    public static String byte2Hex(byte[] b){
        StringBuilder hs= new StringBuilder();
        String stmp="";
        for (byte aB : b) {
            stmp = (Integer.toHexString(aB & 0XFF));
            if (stmp.length() == 1) {
                hs.append("0").append(stmp);
            } else {
                hs.append(stmp);
            }
            //if(n<b.length-1)hs=hs+":";
        }
        return hs.toString().toUpperCase();
    }
    /**
     * 计算ANSI X9.19 MAC值
     * @param key
     * @param macData 报文数据
     * @return mac值
     */
    public static byte[] CalcPBOCMacX919(byte[] key, byte[] macData) {
        if(key.length!=16){
            return null;
        }
        //将16字节密钥分成左右两个密钥，lKey和rKey
        byte[] lKey = new byte[8];
        byte[] rKey = new byte[8];

        System.arraycopy(key, 0, lKey, 0, 8);
        System.arraycopy(key, 8, rKey, 0, 8);

        //将报文数据分组
        int gNums = (macData.length + (8 - 1)) / 8;
        //偏移量
        int offset = 0 ;
        //输入计算数据
        byte[] edata = null;
        for(int i = 0 ; i < gNums; i++){
            byte[] temp = new byte[8];

            if(i != gNums - 1){
                System.arraycopy(macData, offset, temp, 0, 8);
                offset += 8;
            }else{
                //最后一组数据不足，填充0x00
                System.arraycopy(macData, offset, temp, 0, macData.length - offset);
            }

            if(i == 0){
                //只有第一次不做异或
                edata = enDES(lKey,temp);
            } else {
                //上次分组加密结果和本组报文分组数据作异或操作
                temp = XOR(temp,edata);
                //用lKey加密，得到本次分组加密结果
                edata = enDES(lKey,temp);
            }
        }
        //用rKey解密
        edata = deDES(rKey, edata);
        //用lKey加密
        edata = enDES(lKey,edata);

        return edata;
    }
}
